package com.vhall.component.framework.core.environment;

import org.springframework.boot.env.PropertySourceLoader;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;

/**
 * 加载配置文件
 *
 * @author xiaoliang.wang@vhall.com
 */
@SuppressWarnings("unchecked")
public abstract class AbstractPropertySourceDetector implements PropertySourceLoader {

    public boolean support(PropertySourceLoader propertyLoader, String fileExtension) {
        String[] fileExtensions = propertyLoader.getFileExtensions();
        return null != fileExtensions
                && Arrays.stream(fileExtensions).anyMatch(extension -> extension.equals(fileExtension));
    }

    protected void addPropertySource(ConfigurableEnvironment environment, PropertySource<?> newSource) {
        final String starget = newSource.getName();
        MutablePropertySources resources = environment.getPropertySources();
        Iterator<PropertySource<?>> iterator = resources.iterator();
        while (iterator.hasNext()) {
            PropertySource<?> oldSource = iterator.next();
            if (oldSource.getName().contains(starget)) {
                mergeSource(oldSource, newSource);
                break;
            }
        }
    }

    /**
     * 合并相同配置文件的属性, 新配置属性覆盖老配置属性
     *
     * @param oldSource
     * @param newSource
     * @return
     */
    private PropertySource<?> mergeSource(PropertySource<?> oldSource, PropertySource<?> newSource) {
        Object oldMap = oldSource.getSource();
        Object newMap = newSource.getSource();
        if (newMap instanceof Map && oldMap instanceof Map) {
            Map<String, Object> newProperties = (Map<String, Object>) newMap;
            Map<String, Object> oldProperties = (Map<String, Object>) oldMap;

            for (Map.Entry<String, Object> entry : newProperties.entrySet()) {
                oldProperties.put(entry.getKey(), entry.getValue());
            }
        }
        return oldSource;
    }

    protected String getContentStringFromResource(Resource resource) throws IOException {
        return StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);
    }

}
